package org.opens.lambda.parallel;

import org.junit.Test;

import java.util.Comparator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class SpliteratorInAction {

    private static String text = "d1" +
            "\n" +
            "d2" +
            "\n" +
            "d3" +
            "\n" +
            "d4" +
            "\n" +
            "d5" +
            "\n" +
            "d6" +
            "\n" +
            "d7" +
            "\n" +
            "d8" +
            "\n" +
            "d9" +
            "\n" +
            "d10" +
            "\n" +
            "d11" +
            "\n" +
            "d12";

    @Test
    public void test1() {
        IntStream intStream = IntStream.rangeClosed(0, 10);
        Spliterator.OfInt spliterator = intStream.spliterator();
        Consumer<Integer> consumer = i -> System.out.println(i);
        spliterator.forEachRemaining(consumer);
    }

    @Test
    public void test2() {
        MySpliteratorText mySpliteratorText = new MySpliteratorText(text);
        mySpliteratorText.stream().forEach(System.out::println);
    }

    /**
     * 说明:
     *      1. 其实产生并行化对象只是将其中得一个字段设置为true.
     *          - 流式语法并不是走一句执行一句, (未理解), 所以在此处反复串行化, 并行化, 串行化..., 最终流的状态是由最后
     *          一个状态决定串行还是并行的, 并且idea也给出了只能提示, 前面的串行/并行化函数变为了灰色.
     */
    @Test
    public void test33() {
        IntStream intStream = IntStream.rangeClosed(0, 100);
        intStream.parallel()
                .filter(null)
                .sequential()
                .map(null)
                .parallel()
                .forEach(null);
    }

    static class MySpliteratorText {

        private final String[] data;

        public MySpliteratorText(String text) {
            Objects.requireNonNull(text, "the parameter can not be null");
            this.data = text.split("\n");
        }

        public Stream<String> stream() {
            return StreamSupport.stream(new MySpliterator(), false);
        }

        public Stream<String> parallelStream() {
            return StreamSupport.stream(new MySpliterator(), true);
        }

        private class MySpliterator implements Spliterator<String> {

            private int start;

            private int end;

            public MySpliterator() {
                this.start = 0;
                //MySpliteratorText.this表示的是MySpliteratorText的实例对象
                this.end = MySpliteratorText.this.data.length - 1;
                System.out.println(end);
            }

            public MySpliterator(int start, int end) {
                this.start = start;
                this.end = end;
            }

            /**
             * 说明:
             *      1. 如果stream中的元素时可以知道的, 就返回.
             */
            @Override
            public long getExactSizeIfKnown() {
                return estimateSize();
            }

            /**
             * 功能:
             *      如果存在剩余元素, 就对其执行给定的aciton操作, 否则返回null.
             * @param action    对stream中元素的消费行为
             * @return          没有剩余元素时返回false.
             */
            @Override
            public boolean tryAdvance(Consumer<? super String> action) {
                if(start <= end) {
                    action.accept(MySpliteratorText.this.data[start++]);
                    return true;
                }
                return false;
            }

            @Override
            public Spliterator<String> trySplit() {
                int middle = ( end - start ) / 2;
                if(middle <= 1) {
                    return null;
                }
                int left = start;
                int right = start + middle;
                start = start + middle + 1;
                return new MySpliterator(left, right);
            }

            /**
             * 功能:
             *      返回遍历将遇到的元素数量的估计值，如果无限，未知或计算成本太高，则返Long的最大值.             *
             */
            @Override
            public long estimateSize() {
                return end - start;
            }

            /**
             * 说明:
             *      1. IMMUTABLE表示不可变的.
             *      2. SIZED表示知道大小的;
             *      3. SUBSIZED表示可以取子集的.
             */
            @Override
            public int characteristics() {
                return IMMUTABLE | SIZED | SUBSIZED;
            }
        }

    }

    /**
     * 说明:
     *      字符串中的换行符可以不转义进行切割.
     * 输出:
     *      12
     *      12
     */
    @Test
    public void test3() {
        System.out.println(text.split("\n").length);
        System.out.println(text.split("\\n").length);
    }

}
